home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / Apple II / Apple II Sample Code / MPW IIGS SC / SC.021.Dynamo / buildapp.manual.text < prev    next >
Encoding:
Text File  |  1990-06-17  |  39.1 KB  |  906 lines  |  [TEXT/MSWD]

  1. Getting started:    Setting up the DYNAMO cross-development system:
  2.                     <<< Version 3.1 >>>
  3.  
  4.  
  5. Step 1:    Copy the DYNAMO folder onto your Macintosh.  Then rename the folder 
  6. to indicate the project.
  7.  
  8. Step 2:    Create a ProDOS disk.  It should be initialized at a 4:1 interleave.  
  9. ProDOS should be copied onto it (get the ProDOS file from a bootable ProDOS 8 
  10. disk, or get the P8 file from the System folder of a GS/OS disk and rename it 
  11. to ProDOS on the floppy).  The BUILDAPP.SYSTEM and BUILDAPP.TEXT files (found 
  12. in the folder prodos.stuff) should be copied to the ProDOS disk via Apple File 
  13. Exchange or copied with the copy.prodos.stuff script.  When copied to the 
  14. ProDOS disk, the filetype/auxtype of BUILDAPP.SYSTEM should be $FF/$0000, and 
  15. the filetype/auxtype of BUILDAPP.TEXT should be $04/$0000.
  16.  
  17. Step 3:    Start MPW by clicking on any of the source files in the project 
  18. directory.  Do a full-build of SAMPLE.  When prompted, insert the ProDOS disk.
  19.  
  20. Step 4:    Insert the ProDOS disk into the Apple II (or IIGS).  Boot it.  (Or 
  21. double click on BUILDAPP.SYSTEM from the finder.)
  22.  
  23. Note that you can build your binary images onto a server.  The BUILDAPP.SYSTEM 
  24. launcher can load them from the server, given the correct build script.  This 
  25. eliminates the need for a floppy disk completely.
  26.  
  27.  
  28. You should now be running the DYNAMO sample application.  This sample is 
  29. simply an exerciser of the DYNAMO runtime routines.  It tests the routines, 
  30. and also the source code demonstrates using the runtime and macro libraries.
  31.  
  32.  
  33.  
  34. Now, for more detail:
  35.  
  36.  
  37.  
  38. The BUILDAPP.SYSTEM program allows the developer to build a multiple-segment 
  39. application into one program file, and to launch it simply on the //e.  
  40. Segments are automatically relocated to appropriate banks of memory, and then 
  41. the application is launched starting at any address in any bank chosen.
  42.  
  43. BUILDAPP.SYSTEM uses a text file as a script for building the application.  
  44. The default name for this text file is BUILDAPP.TEXT.  This can be changed by 
  45. modifying the pathname in the program BUILDAPP.SYSTEM.  The pathname starts at 
  46. the sixth byte of the file, memory location $2006 if BLOADed.  The pathname is 
  47. a pascal string.  (This is the standard ProDOS way of giving the launched 
  48. application a pathname.)
  49.  
  50. To use the BUILDAPP.SYSTEM program, you will need a disk with ProDOS, the 
  51. BUILDAPP.SYSTEM program, a build script file called BUILDAPP.TEXT, and all the 
  52. segments of your application on one disk.  This disk is now bootable.  When 
  53. the disk is booted, BUILDAPP.SYSTEM will construct a single executable block 
  54. of code starting at address $2000.  Then it may or may not prompt you as to 
  55. whether or not you want to save this image.  (The “whether or not” is 
  56. configurable.)  During development, you will often choose not to save it, 
  57. since it takes just that much longer to get the application executing.  Then 
  58. you can test your latest addition or change to your application.  To make a 
  59. bootable disk without BUILDAPP.SYSTEM, you just save the application image to 
  60. disk, and then copy the application to a disk with just ProDOS on it.  If the 
  61. application name ends with .SYSTEM, and it has a filetype of $FF, you have a 
  62. bootable application.
  63.  
  64.  
  65. You may wish to develop on one machine, which writes the segments to the 
  66. ProDOS disk, and then just boot the disk on another machine.  This saves a lot 
  67. of time booting into your development environment.  There is also the 
  68. advantage of always being able to look at the most current source while 
  69. executing the program.  You don't need two machines to develop, but it will 
  70. definitely speed up the add/change/test development cycle every programmer 
  71. goes through.
  72.  
  73.  
  74.  
  75. How the application is build depends on the BUILDAPP.TEXT script file.  Here 
  76. is the explanation of this file:
  77.  
  78. The first line of the build script is the pathname that will be placed at 
  79. $2006 of the application.  You may have no need for this, but if you are 
  80. developing a system application, launchers may place a pathname there, and you 
  81. may want a default.
  82.  
  83. Lines 2-N are for the segments to be loaded.  The first field is the mode 
  84. byte.  Bits 0-2 of the mode byte indicate what bank of memory the segment 
  85. should be transferred to at execution time.
  86.  
  87. Bit 0 indicates ROM or language card.  Off for ROM, on for language card.
  88.  
  89. Bit 1 indicates which language card (if bit 0 is on).  Off for primary 
  90. language card, on for auxiliary language card.
  91.  
  92. Bit 2 indicates 1st or 2nd $D000 bank of language card.  Which language card 
  93. is still indicated by bit 0 and 1.  Off selects the secondary $D000 bank 
  94. ($C083), and on selects the primary $D000 bank ($C08B).
  95.  
  96. Bit 3 indicates primary or auxiliary 48k.  Off for primary, on for auxiliary.
  97.  
  98. Bit 4 indicates that the auxiliary stack pointer should NOT be initialized.  
  99. If you load a block of code or data into the auxiliary language card, the 
  100. auxiliary stack pointer is initialized to $FF unless you indicate otherwise by 
  101. setting this bit on.
  102.  
  103. Bit 7 of the mode byte being on indicates the end of the segment list.  Bits 
  104. 0-3 still indicate a bank of memory, and the following field indicates the 
  105. launch address within that bank.
  106.  
  107. The second field is the load address.  This is the address the segment will be 
  108. moved to at execution time.
  109.  
  110. The third field is the name of the segment itself.  This can be a full or 
  111. partial pathname.
  112.  
  113. The next two lines indicate whether you want hex or decimal information 
  114. indicating starting address and total application size.
  115.  
  116. The next line indicates whether or not you want to be prompted to save the 
  117. file, and if you don’t want to be prompted, what to do instead.  To not be 
  118. prompted, the first character of ths line needs to be a Y, N, or Q (or the 
  119. lowercase equivalent).  You will be prompted if the first character of this 
  120. line is anything else.  (Putting a ? here if you want to be prompted isn’t a 
  121. bad idea.  It acts as a placeholder, and is reasonably descriptive.)
  122.  
  123. The final line indicates the application filetype, auxtype, and filename.  The 
  124. application builder will ask if you want the application saved.  After the 
  125. file is saved (or not), the application is launched for testing.
  126.  
  127. NOTE:  All numeric fields can be decimal or hex.
  128.  
  129. The below is a sample build script that was used to make the application 
  130. builder itself.  
  131.  
  132. There is only one segment for this application.  The runtime was linked into 
  133. the main code module, generating only one binary code segment.
  134.  
  135. BUILDAPP.TEXT                    ;The default script filename.
  136. 0,$800,BUILD.BIN                ;The buildapp application.
  137. $80,$800                        ;Starting address.
  138. $                                ;Display starting address in hex.
  139. $                                ;Display application size in hex.
  140. N                                ;Don’t save file -- just launch it.
  141. $FF,0,BUILDAPP.SYSTEM            ;Filetype, auxtype, and filename.
  142.  
  143. The BUILDAPP.TEXT file can be up to 2045 bytes long.
  144.  
  145. Bank switching will still have to occur within the application, as necessary.  
  146. There is no getting around that on a //e.  BUILDAPP.SYSTEM is to simplify the 
  147. loading and starting of an application, by making it a single, launchable 
  148. file.
  149.  
  150.  
  151.  
  152. Below are the macros included in the runtime, and their basic usage:
  153.  
  154. _____________________________________________________________
  155.  
  156. OPERAND USAGE:
  157.  
  158. If the operand represents an integer variable or string, then you do not put a 
  159. # in front of it.  Variables and strings are always either a ldx literal, or a 
  160. ldy literal, so the # is assumed.  When the macro is expanded, the # is put 
  161. there automatically.
  162.  
  163. If the operand represents a value, then you will need to put a # or an * in 
  164. front of the operand.  If you put a # in front of the operand, then it is a 
  165. literal.  If you put an * in front, then it uses the value at that address.  
  166. This is similar to the C unary operator *.
  167.  
  168. If the operand represents a 1-byte value, then you will need to put a < after 
  169. the # or *.  This tells the macros to load only the accumulator with a value 
  170. (instead of the accumulator and y-register) and call the low-byte-only entry 
  171. point instead.
  172.  
  173. An extension has been added to version 3.1.  You can now have as many levels
  174. of indirection as you want.  A single * gives you a single level of indirection.
  175. (Value at, instead of value.)  Two *’s in a row gives you two levels of
  176. indirection.  This would be equivalent to a double-dereference in c.
  177.  
  178. These macros are interfaces for the runtime routines associated with them.  
  179. The runtime routines handle up to 128 integer variables, and up to 256 
  180. strings.  The runtime also has multi-dimension array support.  The integer 
  181. functions are simple add,sub,mul,div, and others.  These others include mass-
  182. initialization, min, max,  print decimal, etc.  The string functions are most 
  183. of what is available in AppleSoft, in various forms.  The array functions are 
  184. used to define a base pointer to a row of dta within the array, and then to 
  185. index into and out of that row.
  186.  
  187. The principle of the runtime routines is that the xreg holds a destination 
  188. variable number (for ints: 0-254, for strings: 0-255).  All runtimes preserve 
  189. the xreg, therefore, you can do multiple operations to a single variable 
  190. without having to reload the xreg.  The values that are used on the xreg 
  191. variable (the source data), is one of 3 forms for integers:
  192.     1. 1-byte value
  193.     2. 2-byte value
  194.     3. 2-byte integer variable.
  195. 1-byte values are placed in the acc.  2-byte values are placed in the acc,y 
  196. (acc=lo, y=hi).  2-byte integer variables have the variable number placed in 
  197. the yreg.  (The yreg is not preserved by the runtime routines.)  Once the 
  198. source data is loaded (in acc, acc-y, or y), the proper call to the runtime 
  199. routines is made.  The 'proper' routine is based on the type of data the 
  200. source is.  (If the source is a variable, and we are adding, the macro will 
  201. call the addvar routine.)
  202.  
  203. Strings are also referenced by number.  There are 3 tables for strings:
  204.     1. String length table.
  205.     2. Max string length table.
  206.     3. Pointer table.
  207. So, each string takes up four bytes, plus however long the max string length 
  208. is.  Having the pointer allows the program to point into memory that was never 
  209. loaded or initialized.  This can save time loading the application from disk.  
  210. The string routines will never overwrite the buffer space allocated for them.  
  211. The string will be truncated.  So, you can append strings without worry about 
  212. clobbering memory.
  213.  
  214. Some code using the macros and runtime might look like:
  215.  
  216.             _restore    textForBill        ;Point at literal text.
  217.             _readstr    billStr            ;Read text into string.
  218.             _prstr                        ;Print the string.
  219.             _hexpad        #'0'            ;Set hex padding to a 0.
  220.             _rtcout        #'$'            ;Print a $.
  221.             _varcpy        bill,val        ;Set bill to val.
  222.             _addl        ,#5                ;Add 5 to bill.
  223. (****** or:    _add        ,<#5 ******)
  224.             _mulvar        ,factor            ;Multiply bill by factor.
  225.             _vhexout                    ;Print bill in hex.
  226.             rts
  227. textForBill    dc.b        'Bill''s value in hex is:  ',0
  228.  
  229. We could replace the _restore, _readstr, _prstr, with: 
  230. textForBill    _write        'Bill''s value in hex is:  ',0
  231.  
  232. We could still read the text in the _write macro from elsewhere by:
  233.             _restore    textForBill+3    ;Point at literal text.
  234.             _readstr    billStr            ;Read text into string.
  235.  
  236. The +3 skips the jsr to the write routine (generated by _write).  Both the 
  237. _write and _readstr routines stop at a 0.  (The _readstr ending character can 
  238. be changed to whatever you want with the _readend macro, but the default stop 
  239. character is a 0.)
  240.  
  241.  
  242. Below is a list of the macros, and how they are used:
  243.  
  244.  
  245.     _rtreset
  246. This macro initializes everything necessary in the runtime.  This allows a 
  247. resume after the user presses a reset.    
  248.  
  249.  
  250.     _hibitchrs
  251. This macro is used to turn on the hi-bit for characters that are sent to 
  252. rtcout.
  253.  
  254.  
  255.     _lowbitchrs
  256. This macro is used to turn off the hi-bit for characters that are sent to 
  257. rtcout.
  258.  
  259.  
  260.     _regchrs
  261. This macro is used to make sure that characters sent to rtcout are used as-is.  
  262. There will be no modification of the hi-bit.
  263.  
  264.  
  265.     _write &op1,&op2,&op3,...
  266. This macro prints a cstring.  You can use as many operands as MPW allows.  You 
  267. can continue onto the next line with the line continuation character \.  After 
  268. all the operands are processed, the macro places a cstring 0 terminator 
  269. character at the end of the string.  This is done automatically.  Placing one 
  270. there yourself will define an extra one, which will end up being a BRK 
  271. instruction in your code.
  272.  
  273.  
  274.     _writecr
  275. This macro prints a carriage return.
  276.  
  277.  
  278.     _wrcstr    op
  279. This macro prints a c string pointed to by the operand.
  280.  
  281.  
  282.     _rtcout    op
  283. This macro prints a character.  This character is either already in the acc 
  284. (no operand), or what is described by the operand.  The operand can either be 
  285. an absolute or a value in memory.
  286.  
  287.  
  288.     _signed
  289. This macro sets signed mode.  Printing decimal numbers is affected by this.
  290.  
  291.  
  292.     _unsigned
  293. This macro sets unsigned mode.  Printing decimal numbers is affected by this.
  294.  
  295.  
  296.     _chngsgn
  297. This macro does a two's compliment on the variable.  The result is also 
  298. returned in acc,y.
  299.  
  300.  
  301.     _decoutl op
  302. This macro prints a 1-byte decimal value.  This value is either already in the 
  303. acc (no operand), or what is described by the operand.  The operand can either 
  304. be an absolute or a value in memory.
  305.  
  306.  
  307.     _vdecout op
  308. This macro prints a 2-byte decimal value.  This value is stored in a variable.  
  309. The variable number is either already in the xreg (no operand), or is 
  310. determined by the operand.
  311.  
  312.  
  313.     _decout op
  314. This macro prints a 1- or 2-byte decimal value.  This value is either already 
  315. in the acc,y (no operand), or what is described by the operand.  The operand 
  316. can either be an absolute or a value in memory.  This macro optimizes.  If the 
  317. operand is an immediate value, and it is indicated to be a 1-byte value (by 
  318. using <), then code is generated only to load the acc and decoutl is called 
  319. instead of decout.
  320.  
  321.  
  322.     _hexpad op
  323. This macro sets pad mode for hex.  The value is either already in the acc (no 
  324. operand), or what is described by the operand.  The operand can either be an 
  325. absolute or a value in memory.  Printing hex numbers is affected by this.
  326.  
  327.  
  328.     _hexnopad
  329. This macro sets no pad mode for hex.  Printing hex numbers is affected by 
  330. this.
  331.  
  332.  
  333.     _hexoutl op
  334. This macro prints a 1-byte hex value.  This value is either already in the acc 
  335. (no operand), or what is described by the operand.  The operand can either be 
  336. an absolute or a value in memory.  Since it is only printing a 1-byte value, 
  337. the maximum amount of padding is one character.
  338.  
  339.  
  340.     _vhexout op
  341. This macro prints a 2-byte hex value.  This value is stored in a variable.  
  342. The variable number is either already in the xreg (no operand), or is 
  343. determined by the operand.  The maximum amount of padding is three characters.
  344.  
  345.  
  346.     _hexout op
  347. This macro prints a 2-byte hex value.  This value is either already in the 
  348. acc,y (no operand), or what is described by the operand.  The operand can 
  349. either be an absolute or a value in memory.  The maximum amount of padding is 
  350. three characters.
  351.  
  352.  
  353.     _addvar op1,op2
  354. This macro adds a variable to the destination variable.  If there is no op1, 
  355. then the destination variable number is assumed to be in the xreg.  If there 
  356. is no op2, then the source variable number is assumed to be in the yreg.  The 
  357. value of the source variable is returned in acc,y.
  358.  
  359.  
  360.     _addl op1,op2
  361. This macro adds a 1-byte value to the destination variable.  If there is no 
  362. op1, then the destination variable number is assumed to be in the xreg.  If 
  363. there is no op2, then the value is assumed to be in the acc.  The 1-byte value 
  364. is returned in acc.  The yreg is set to 0.
  365.  
  366.  
  367.     _add op1,op2
  368. This macro adds a 2-byte value to the destination variable.  If there is no 
  369. op1, then the destination variable number is assumed to be in the xreg.  If 
  370. there is no op2, then the value is assumed to be in acc,y.  The 2-byte value 
  371. is returned in acc,y.  This macro optimizes.  If op2 is an immediate value, 
  372. and it is indicated to be a 1-byte value (by using <), then code is generated 
  373. only to load the acc and addconl is called instead of addcon.
  374.  
  375.  
  376.     _subvar op1,op2
  377. This macro subtracts a variable from the destination variable.  If there is no 
  378. op1, then the destination variable number is assumed to be in the xreg.  If 
  379. there is no op2, then the source variable number is assumed to be in the yreg.  
  380. The value of the source variable is returned in acc,y.
  381.  
  382.  
  383.     _subl op1,op2
  384. This macro subtracts a 1-byte value from the destination variable.  If there 
  385. is no op1, then the destination variable number is assumed to be in the xreg.  
  386. If there is no op2, then the value is assumed to be in the acc.  The 1-byte 
  387. value is returned in acc.  The yreg is set to 0.
  388.  
  389.  
  390.     _sub op1,op2
  391. This macro subtracts a 2-byte value from the destination variable.  If there 
  392. is no op1, then the destination variable number is assumed to be in the xreg.  
  393. If there is no op2, then the value is assumed to be in acc,y.  The 2-byte 
  394. value is returned in acc,y.  This macro optimizes.  If op2 is an immediate 
  395. value, and it is indicated to be a 1-byte value (by using <), then code is 
  396. generated only to load the acc and subconl is called instead of subcon.
  397.  
  398.  
  399.     _mulvar op1,op2
  400. This macro multiplies the destination variable by a variable.  If there is no 
  401. op1, then the destination variable number is assumed to be in the xreg.  If 
  402. there is no op2, then the source variable number is assumed to be in the yreg.  
  403. The result of the multiply is also returned in acc,y.
  404.  
  405.  
  406.     _mull op1,op2
  407. This macro multiplies the destination variable by a 1-byte value.  If there is 
  408. no op1, then the destination variable number is assumed to be in the xreg.  If 
  409. there is no op2, then the value is assumed to be in the acc.  The result of 
  410. the multiply is also returned in acc,y.
  411.  
  412.  
  413.     _mul op1,op2
  414. This macro multiplies the destination variable by a 2-byte value.  If there is 
  415. no op1, then the destination variable number is assumed to be in the xreg.  If 
  416. there is no op2, then the value is assumed to be in acc,y.   The result of the 
  417. multiply is also returned in acc,y.  This macro optimizes.  If op2 is an 
  418. immediate value, and it is indicated to be a 1-byte value (by using <), then 
  419. code is generated only to load the acc and _mulconl is called instead of 
  420. mulcon.
  421.  
  422.  
  423.     _divvar op1,op2
  424. This macro divides the destination variable by a variable.  If there is no 
  425. op1, then the destination variable number is assumed to be in the xreg.  If 
  426. there is no op2, then the source variable number is assumed to be in the yreg.  
  427. The remainder from the divide is returned in acc,y.
  428.  
  429.  
  430.     _divl op1,op2
  431. This macro divides the destination variable by a 1-byte value.  If there is no 
  432. op1, then the destination variable number is assumed to be in the xreg.  If 
  433. there is no op2, then the value is assumed to be in the acc.  The remainder 
  434. from the divide is returned in acc,y.
  435.  
  436.  
  437.     _div op1,op2
  438. This macro divides the destination variable by a 2-byte value.  If there is no 
  439. op1, then the destination variable number is assumed to be in the xreg.  If 
  440. there is no op2, then the value is assumed to be in acc,y.  The remainder from 
  441. the divide returned in acc,y.  This macro optimizes.  If op2 is an immediate 
  442. value, and it is indicated to be a 1-byte value (by using <), then code is 
  443. generated only to load the acc and _divconl is called instead of divcon.
  444.  
  445.  
  446.     _var op
  447. This macro sets the current variable.  The current variable is defined by a 
  448. number in the xreg.  All runtime functions preserve the xreg, so multiple 
  449. operations can be done to the same variable without having to reload the xreg 
  450. with the variable number.
  451.  
  452.  
  453.     _set0 op
  454. This macro sets a variable to 0.  If there is no op1, then the destination 
  455. variable number is assumed to be in the xreg.  The acc is set to 0.
  456.  
  457.  
  458.     _varcpy op1,op2
  459. This macro sets a variable to another variable.  If there is no op1, then the 
  460. destination variable number is assumed to be in the xreg.  If there is no op2, 
  461. then the source variable number is assumed to be in the yreg.
  462.  
  463.  
  464.     _setl op1,op2
  465. This macro sets a variable to a 1-byte value.  If there is no op1, then the 
  466. destination variable number is assumed to be in the xreg.  If there is no op2, 
  467. then the value is assumed to be in the acc.
  468.  
  469.  
  470.     _set op1,op2
  471. This macro sets a variable to a 2-byte value.  If there is no op1, then the 
  472. destination variable number is assumed to be in the xreg.  If there is no op2, 
  473. then the value is assumed to be in acc,y.  The 1-byte value is returned in 
  474. acc.  The yreg is set to 0.  This macro optimizes.  If op2 is an immediate 
  475. value, and it is indicated to be a 1-byte value (by using <), then code is 
  476. generated only to load the acc and _setconl is called instead of setcon.
  477.  
  478.  
  479.  
  480.     _vderef    op
  481. This macro uses a variable as a pointer and sets that variable to the value
  482. to where that pointer currently points.  The macro preserves all registers.
  483. The c equivalent would be (using longs instead if ints):
  484.     long    *ptrvar;
  485.     ptrvar = (long *)*ptrvar;
  486.  
  487.  
  488.  
  489.     _setvars op1,op2,op3,op4,...
  490. This macro sets multiple variables to constant values.  The macro is followed 
  491. by as many operands as MPW allows.  The line continuation character \ can be 
  492. used.  The odd operands are the variables to be set, and the even operands are 
  493. the values they should be set to.  Operand1 gets the value of operand 2, and 
  494. so on.  The macro automatically terminates the list with a 255 byte.  This is 
  495. why 255 is not allowed as a variable number.
  496.  
  497.  
  498.     _minswap op1,op2
  499. This macro swaps the two variables if the xreg variable is bigger than the 
  500. yreg variable.  If there is no op1, then the destination variable number is 
  501. assumed to be in the xreg.  If there is no op2, then the source variable 
  502. number is assumed to be in the yreg.
  503.  
  504.  
  505.     _maxswap op1,op2
  506. This macro swaps the two variables if the xreg variable is smaller than the 
  507. yreg variable.  If there is no op1, then the destination variable number is 
  508. assumed to be in the xreg.  If there is no op2, then the source variable 
  509. number is assumed to be in the yreg.
  510.  
  511.  
  512.     _vsgncmp op1,op2
  513. This macro does a signed compare of two variables.  The equal status is true 
  514. if the variables are equal.  If the xreg variable is greater or equal, then 
  515. the carry is set.  If the xreg variable is smaller, then the carry is clear.  
  516. If there is no op1, then the variable number is assumed to be in the xreg.  If 
  517. there is no op2, then the variable number is assumed to be in the yreg.  Once 
  518. op1 and op2 are loaded into the registers, if necessary, the registers are 
  519. preserved.
  520.  
  521.  
  522.     _vcmp op1,op2
  523. This macro does an unsigned compare of two variables.  The equal status is 
  524. true if the variables are equal.  If the xreg variable is greater or equal, 
  525. then the carry is set.  If the xreg variable is smaller, then the carry is 
  526. clear.  If there is no op1, then the variable number is assumed to be in the 
  527. xreg.  If there is no op2, then the variable number is assumed to be in the 
  528. yreg.  Once op1 and op2 are loaded into the registers, if necessary, the 
  529. registers are preserved.
  530.  
  531.  
  532.     _sgncmp op1,op2
  533. This macro works the same as _vsgncmp, except that it compares a variable to a 
  534. constant.  Once op1 and op2 are loaded into the registers, if necessary, the 
  535. registers are preserved.
  536.  
  537.  
  538.     _cmp op1,op2
  539. This macro works the same as _vcmp, except that it compares a variable to a 
  540. constant.  All Once op1 and op2 are loaded into the registers, if necessary, 
  541. the registers are preserved.
  542.  
  543.  
  544.     _rndseed op
  545. This macro is used to seed the random number generator.  If there is no op1, 
  546. then the random seed is assumed to be in the acc,y.
  547.  
  548.  
  549.     _random op
  550. This macro is used to return a random number from 0 to op - 1.  If there is no 
  551. op1, then the random number limit is assumed to be in the acc,y.
  552.  
  553.  
  554.     _strval op
  555. This macro takes the value of a string and returns it in the acc,y.  If there 
  556. is no op1, then the string number is assumed to be in the xreg.
  557.  
  558.  
  559.     _midstrval op1,op2
  560. This macro takes the value of op1 string starting at op2 character and returns 
  561. it in the acc,y.  If there is no op1, then the string number is assumed to be 
  562. in the xreg.  If there is no op2, then the character number is assumed to be 
  563. in the yreg.
  564.  
  565.  
  566.     _prstr op
  567. This macro prints the entire string.  If there is no op1, then the string 
  568. number is assumed to be in the xreg.
  569.  
  570.  
  571.     _prleftstr op1,op2
  572. This macro prints op1 string starting at the first character for op2 
  573. characters.  If there is no op1, then the string number is assumed to be in 
  574. the xreg.  If there is no op2, then the number of characters is assumed to be 
  575. in the acc.
  576.  
  577.  
  578.     _prmidstr op1,op2,op3
  579. This macro prints op1 string starting at the op2 character for op3 characters.  
  580. If there is no op1, then the string number is assumed to be in the xreg.  If 
  581. there is no op2, then the character number is assumed to be in the yreg.  If 
  582. there is no op3, then the number of characters is assumed to be in the acc.
  583.  
  584.  
  585.     _leftstrcpy op1,op2,op3
  586. This macro copies op3 characters from op2 string to op1 string.  If there is 
  587. no op1, then the destination string number is assumed to be in the xreg.  If 
  588. there is no op2, then the source string number is assumed to be in the yreg.  
  589. If there is no op3, then the number of characters is assumed to be in the acc.
  590.  
  591.  
  592.     _strcpy op1,op2
  593. This macro copies op2 string to op1 string.  If there is no op1, then the 
  594. destination string number is assumed to be in the xreg.  If there is no op2, 
  595. then the source string number is assumed to be in the yreg.
  596.  
  597.  
  598.     _midstrcpy op1,op2,op3,op4
  599. This macro copies op4 characters, starting at op3 character from op2 string to 
  600. op1 string.  If there is no op1, then the destination string number is assumed 
  601. to be in the xreg.  If there is no op2, then the source string number is 
  602. assumed to be in the yreg.  If there is no op3, then the character number is 
  603. assumed to be in the acc.  If there is no op4, then all characters to the end 
  604. of the source string will be copied to the destination string.  The op4 case 
  605. is the only case where the assumed value is a particular value (#255), instead 
  606. of what is in a register.  This is the case because there are only three 
  607. registers.
  608.  
  609.  
  610.     _leftstrcat op1,op2,op3
  611. This macro concatenates op3 characters of op2 string onto op1 string.  If 
  612. there is no op1, then the destination string number is assumed to be in the 
  613. xreg.  If there is no op2, then the source string number is assumed to be in 
  614. the yreg.  If there is no op3, then the number of characters is assumed to be 
  615. in the acc.
  616.  
  617.  
  618.     _strcat op1,op2
  619. This macro concatenates op2 string onto op1 string.  If there is no op1, then 
  620. the destination string number is assumed to be in the xreg.  If there is no 
  621. op2, then the source string number is assumed to be in the yreg.
  622.  
  623.  
  624.     _midstrcat op1,op2,op3,op4
  625. This macro concatenates op4 characters starting at op3 character from op2 
  626. string onto op1 string.  If there is no op1, then the destination string 
  627. number is assumed to be in the xreg.  If there is no op2, then the source 
  628. string number is assumed to be in the yreg.  If there is no op3, then the 
  629. character number is assumed to be in the acc.  If there is no op4, then all 
  630. characters to the end of the source string will be concatenated to the 
  631. destination string.  The op4 case is the only case where the assumed value is 
  632. a particular value (#255), instead of what is in a register.  This is the case 
  633. because there are only three registers.
  634.  
  635.  
  636.     _litstr op1,op2,op3,...
  637. This macro works very much like _write, except that the characters are not 
  638. printed.  They are copied into the designated string.  If there is no 
  639. designated string, then it is assumed that the xreg already holds the string 
  640. number.
  641.  
  642.  
  643.     _strchr op1,op2
  644. This macro returns the op2th character of op1 string.  If there is no op1, 
  645. then the destination string number is assumed to be in the xreg.  If there is 
  646. no op2, then the character number is assumed to be in the acc.
  647.  
  648.  
  649.     _strloc op1
  650. This macro returns the physical location of op1 string in memory.  The string 
  651. location is returned in acc,y.If there is no op1, then the destination string 
  652. number is assumed to be in the xreg.
  653.  
  654.  
  655.     _cstr op1,op2,op3,...
  656. This macro is used to generate a cstring using the same syntax as other 
  657. macros.  It works very much like _write and _litstr in the way it handles 
  658. parameters.  The only thing that this macro does, however, is define data.
  659.  
  660.  
  661.     _restore op
  662. This macro sets the read data pointer.  If there is no op, then the address 
  663. for reading data is assumed to be in the acc,y.
  664.  
  665.  
  666.     _readint op
  667. This macro reads an int from the current data pointer and advances the pointer 
  668. by two bytes.  If there is no op1, then the destination variable number is 
  669. assumed to be in the xreg.
  670.  
  671.  
  672.     _readstr op
  673. This macro reads string data into the designated string until the end-of-
  674. string character is encountered.  The data pointer is then set to point after 
  675. this end-of-string character.  If there is no op1, then the destination string 
  676. number is assumed to be in the xreg.
  677.  
  678.  
  679.     _readend op
  680. This macro is used to set the end-of-string character for _readstr.  If there 
  681. is no op1, then the _readstr ending character is assumed to be in the acc.
  682.  
  683.  
  684. The array handling is simple pointer-based storage and retrieval.  There is 
  685. also some logic for multiple-dimensioned arrays.  This system can handle 
  686. arrays up to four dimensions deep.  With a little work, this can be expanded 
  687. to any number.  The system allows for easy expansion to more dimensions.  It 
  688. works by having the application first give a description of the array.  This 
  689. description consists of the location of the array, the size of the elements in 
  690. the array (byte or word), and what size the dimensions are.  There are 
  691. actually four pointers into the array area.  The first one is always the base 
  692. address.  When the base address is first established, all four pointers are 
  693. set to the base address.  If you then wish to index into the array, you tell 
  694. the runtime at what point in the array you wish to access for each level of 
  695. subscript.  If a subscript is omitted at the beginning of the index list, then 
  696. it is assumed that the pointer for that level is already what you want.  If a 
  697. subscript is omitted after the first subscript, then that subscript is assumed 
  698. to be 0.
  699.  
  700. For example:
  701. We have a four dimensional array of words, called things, equated to 
  702. address $4000.  We would declare the array with the _array macro as 
  703. follows:
  704.     _array #things,w,#3,#4,#5,#6
  705.  
  706. This line means "use the memory at #things as an array of words that is 
  707. 3 by 4 by 5 by 6 in size."  The array handling routines now use this 
  708. information when getting and putting data to the array.  The routines 
  709. only keep track of one array.  If you wish to switch between two or more 
  710. arrays, you will have to reissue _array commands.  The _array command 
  711. does not allocate or protect any memory.  It just gets the relevant 
  712. information for the array.  Thus, you can switch arrays as often as you 
  713. want.  Of course, there is some time overhead in switching, but it is 
  714. rather minimal.
  715.  
  716. If we wished to get the element things(1,3,4,5), and place it in the 
  717. variable thing, we would do the following:
  718.         _index    #1,#3,#4
  719.         _getw    thing,#5
  720.  
  721. The _index macro builds pointers for the array into each level of 
  722. subscript.  The _getw macro indexes (using #5) from the lowest level 
  723. pointer, and gets that word and stores it in the variable thing.  If we 
  724. then wish to get the element things(1,3,4,4), we would:
  725.         _getw    thing,#4
  726.  
  727. We don't have to recalculate any pointers.  They are still intact from 
  728. the above _index macro.  If we wish to change any of the subscripts, 
  729. other than the last one, we will have to issue another _index macro.  
  730. Lets say that we want the element things(1,2,0,5).  Knowing that the 
  731. previous _index macro got the element things(1,3,4,5), we can minimize 
  732. the pointer math by having the _index macro redo only the data that is 
  733. no longer valid.  We would do an _index macro as follows:
  734.         _index    ,#2
  735.         _getw    thing,#5
  736.  
  737. The first subscript is the same.  Therefore, the pointer for the first 
  738. subscript is correct.  The pointer for the second subscript is generated 
  739. from the first (just as the pointer for the first is generated from the 
  740. base address of the array).  So, we don't have to mention the first 
  741. subscript again.  Not doing so saves code.  Once any subscript pointer 
  742. is recalculated, all the lower level pointers are set to that value.  
  743. This means that there is an assumption that all the remaining subscripts 
  744. are zero.  If this is indeed the case, they don't have to be mentioned 
  745. either.  In this example, the third subscript is zero.  So, it doesn't 
  746. have to be mentioned either.  This method of separate pointers for 
  747. different levels of the array can be very efficient.  It also can be 
  748. confusing.  If it is not clear whether you can leave subscripts out, 
  749. don't.  It will still work with all of the subscripts, although it will 
  750. be more code than necessary.
  751.  
  752. There is another form of the _index macro.  It is the _vindex macro.  
  753. This is used when the index value is stored in a variable.  One 
  754. unfortunate syntax limitation is that you can't mix the two types on one 
  755. line.  You still can mix the two types, however, when indexing into an 
  756. array.  For example:
  757.     bob = things(color, 3, type, 5)
  758.  
  759. would be done like:
  760.     _vindex        color
  761.     _index        ,#3
  762.     _vindex        ,,type
  763.     _getw        bob,#5
  764.  
  765.  
  766. The following macros are used to define and access arrays.
  767.  
  768.     _array loc,elesize,op1,op2,op3,op4
  769. This macro prepares the array handling routines to work on the defined array.  
  770. The operand loc is either the address of the array (when preceded by a # 
  771. sign), or a 2-byte location where the address to the array is stored (when 
  772. preceded by an *).  The operand elesize determines the size of the elements in 
  773. the array.  The elements can be either bytes or words.  The operand elesize 
  774. should be either a b or a w.  Operands op1 through op4 describe the dimensions 
  775. of the array.  These must be constants.  Operands op2 through op4 are 
  776. optional.  The array may only be linear, in which case, op2 through op4 would 
  777. have no function.  The operand op1 is actually not used.  It is just for 
  778. commenting purposes.  The array routines do not do any range checking, and all 
  779. that op1 is good for is to determine if the first subscript is out of range.  
  780. You must have an op1, however, as a placeholder.  This is to encourage it 
  781. being used, as it is useful when reading the source code.
  782.  
  783.  
  784.     _index op1,op2,op3
  785. This macro is used to calculate a pointer into the array.  There are actually 
  786. four pointers.  The first three are used as partial results from previous 
  787. calculations, so that all subscripts don't have to be involved every time 
  788. there is a calculation to determine the specific element of the array.  When 
  789. the pointer for op1 is calculated, the resulting offset is added to the base 
  790. array pointer (defined with the _array macro).  This is then stored as the 
  791. 2nd, 3rd, and 4th level pointers.  If there are no more operands, then the 
  792. effective pointer into the array will be this value.  If op2 and op3 were 
  793. zero, then this value would be correct.  The assumption in this case is that 
  794. any undeclared subscripts beyond the first one declared are zero.  So, if your 
  795. array is only two-dimensional, you would then never declare an op2 or op3, and 
  796. they would therefore never affect the pointer into the array.  An interesting 
  797. aside to this is that one array can actually be considered to have a variable 
  798. number of dimensions.  Let's say that you have an array that is 10x10x10.  
  799. This array could also be viewed as a 10x100 array.  Both have the same number 
  800. of elements.  Using the _index macro differently, you could access the array 
  801. either way.  For example:
  802.     _index    #5
  803.     _getw    value,#55
  804. would work as well as
  805.     _index    #5,#5
  806.     _getw    value,#5
  807. This flexibility can be very useful.  (It can also be confusing.)  If you have 
  808. a case where you know that the first subscript is the same as the last time 
  809. you used the _index (or _vindex) macro, you can choose not to restate that 
  810. subscript.  You might even have a situation where the second subscript is the 
  811. same also.  In these cases, you can choose to leave those operand fields 
  812. empty.  This will produce less code than if you mentioned them.  (There is an 
  813. overhead of 7 bytes per index with the _index macro, and an overhead of 5 
  814. bytes with the _vindex macro.)
  815. The syntax for this would look like:  _index  ,,#5
  816. The commas are necessary to indicate that subscripts 1 and 2 are already 
  817. defined, and that you are referring to subscript 3.  If the commas were not 
  818. there, the _index macro would assume that the #5 is the first subscript, and 
  819. that subscripts 2 and 3 are zero, or not used at all.  This macro optimizes.  
  820. If an operand is an immediate value, and it is indicated to be a 1-byte value 
  821. (by using <), then code is generated only to load the acc and arraylindxN is 
  822. called instead of arrayindxN.
  823.  
  824.  
  825.     _vindex op1,op2,op3
  826. This macro works just like _index, except that the operands are variables, 
  827. instead of constants or values at a particular memory location.  This is 
  828. useful when you want to use variable subscripts.
  829.  
  830.  
  831.     _getb op1,op2
  832. This macro is used to get a 1-byte value from the array.  The operand op2 is 
  833. the right-most subscript in the array.  This value can be either a constant, 
  834. or a value in memory.  The operand op1 is the variable to store the array 
  835. value into.  The low byte of the variable will be set to the value, and the 
  836. hi-byte will be set to zero.  This macro optimizes.  If op2 is an immediate 
  837. value, and it is indicated to be a 1-byte value (by using <), then code is 
  838. generated only to load the acc and getbytel is called instead of getbyte.
  839.  
  840.  
  841.     _getbl op1,op2
  842. This macro is used to get a 1-byte value from the array using a 1-byte index.  
  843. The operand op2 is the right-most subscript in the array.  This value can be 
  844. either a constant, or a value in memory.  The operand op1 is the variable to 
  845. store the array value into.  The low byte of the variable will be set to the 
  846. value, and the hi-byte will be set to zero.
  847.  
  848.  
  849.     _vgetb op1,op2
  850. This macro works just like _getb, except that the operand op2 is a variable.
  851.  
  852.  
  853.     _getw op1,op2
  854. This macro works just like _getb, except that the value from the array is a 
  855. word, instead of a byte.  This macro optimizes.  If op2 is an immediate value, 
  856. and it is indicated to be a 1-byte value (by using <), then code is generated 
  857. only to load the acc and getwordl is called instead of getword.
  858.  
  859.  
  860.     _getwl op1,op2
  861. This macro works just like _getbl, except that the value from the array is a 
  862. word, instead of a byte.
  863.  
  864.  
  865.     _vgetw op1,op2
  866. This macro works just like _getw, except that the operand op2 is a variable.
  867.  
  868.  
  869.     _putb op1,op2
  870. This macro places the low byte of the variable op1 into the array at the point 
  871. described by the right-most subscript op2.  The operand op2 is either a 
  872. constant, or a location in memory where the subscript is stored.  This macro 
  873. optimizes.  If op2 is an immediate value, and it is indicated to be a 1-byte 
  874. value (by using <), then code is generated only to load the acc and putbytel 
  875. is called instead of putbyte.
  876.  
  877.  
  878.     _putbl op1,op2
  879. This macro places the low byte of the variable op1 into the array at the point 
  880. described by the right-most 1-byte subscript op2.  The operand op2 is either a 
  881. constant, or a location in memory where the subscript is stored.
  882.  
  883.  
  884.     _vputb op1,op2
  885. This macro works just like _getb, except that the operand op2 is a variable.
  886.  
  887.  
  888.     _putw op1,op2
  889. This macro places the variable's value into the array at the point described 
  890. by the right-most subscript op2.  The operand op2 is either a constant, or a 
  891. location in memory where the subscript is stored.  This macro optimizes.  If 
  892. op2 is an immediate value, and it is indicated to be a 1-byte value (by using 
  893. <), then code is generated only to load the acc and putwordl is called instead 
  894. of putword.
  895.  
  896.  
  897.     _putw op1,op2
  898. This macro places the variable's value into the array at the point described 
  899. by the right-most 1-byte subscript op2.  The operand op2 is either a constant, 
  900. or a location in memory where the subscript is stored.
  901.  
  902.  
  903.     _vputw op1,op2
  904. This macro works just like _getw, except that the operand op2 is a variable.
  905.  
  906.